package com.lancoo.ccas53.arrangecourse.coursescheduling.campusscheduling;

import cn.hutool.core.util.StrUtil;
import com.lancoo.ccas53.arrangecourse.AlgDataSource.common.SchedulingProcessData;
import com.lancoo.ccas53.arrangecourse.coursescheduling.allocatetimeslotroom.AllocateNoClashTimeslotRoom;
import com.lancoo.ccas53.arrangecourse.coursescheduling.allocatetimeslotroom.AllocateTimeslotRoom;
import com.lancoo.ccas53.arrangecourse.coursescheduling.assignlist.NoClashAssign;
import com.lancoo.ccas53.arrangecourse.coursescheduling.assignlist.NormalAssign;
import com.lancoo.ccas53.arrangecourse.entities.ClassHour;
import com.lancoo.ccas53.arrangecourse.entities.TeachingClassUnit;
import com.lancoo.ccas53.arrangecourse.entities.TimeslotRoom;
import com.lancoo.ccas53.arrangecourse.rulecheck.RuleInit;
import com.lancoo.ccas53.entity.SubClassGroup;
import com.lancoo.ccas53.pojo.dto.ArrangeCourseRuleDto;
import com.lancoo.ccas53.pojo.dto.ArrangeTeacherRuleDto;
import com.lancoo.ccas53.pojo.dto.ArrangeTeachingClassDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;

/**
 * @Description 手动指定排课
 * @Author Fortysun
 * @Date 2023/4/25 10:50
 **/
@Slf4j
public class CampusScheduling {
    //排课规则初始化对象
    RuleInit ruleInit;
    //声明无冲突排课对象
    private NormalAssign noClashScheduing;

    /**
     * 构造函数，初始化按类型，处理教室课时分组列的对象，同时传递排课规则初始化对象
     * @param ruleInit 排课规则初始化类
     */
    public CampusScheduling(RuleInit ruleInit) {
        this.ruleInit = ruleInit;
        //初始化，按教室类型，处理教室课时分组信息列表的对象
        //初始化排课的对象
        if (noClashScheduing == null) {
            //初始化排课使用的教室课时分配的类，分配无冲突的教室课时分组信息；
            AllocateTimeslotRoom allocateNoClashTimeslotRoom = new AllocateNoClashTimeslotRoom();
            //初始化拆班排课，需要满足的规则
            noClashScheduing = new NoClashAssign(ruleInit.getNoClashBaseRule(), allocateNoClashTimeslotRoom);
        }
    }

    public LinkedList<TeachingClassUnit> classStart(Integer taskId,
                                               String campusId,
                                               List<ArrangeTeachingClassDto> teachingClassList,
                                               LinkedList<TimeslotRoom> timeslotRoomList,
                                               ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap,
                                               List<ArrangeTeacherRuleDto> teacherRuleList,
                                               List<ArrangeCourseRuleDto> courseRuleList,
                                               LinkedList<TeachingClassUnit> leaveList,
                                               List<SubClassGroup> subGroupList) {
        log.info("#CampusScheduling.start#--校区：" + campusId
                + "按行政班排课开始"
                + "排课教学班数量：" + (teachingClassList != null ? teachingClassList.size() : 0));

        leaveList = mergeClassStart(taskId, campusId,
                teachingClassList, timeslotRoomList, classHourMap,
                teacherRuleList, courseRuleList, leaveList, subGroupList);


        if (teachingClassList != null && !teachingClassList.isEmpty()) {
            log.info("#CampusScheduling.start#--校区：" + campusId
                    + "按行政班排课开始"
                    + "行政班排课开始"
                    + "排课教学班数量：" + (teachingClassList != null ? teachingClassList.size() : 0)
                    + "剩余合班排课单元数量：" + (leaveList != null ? leaveList.size() : 0)
            );
            Map<String, List<ArrangeTeachingClassDto>> classMap = teachingClassList.stream().collect(Collectors.groupingBy(ArrangeTeachingClassDto::getToClass));
            for (Map.Entry<String, List<ArrangeTeachingClassDto>> entry : classMap.entrySet()) {
                leaveList = start(taskId, campusId, entry.getValue(), timeslotRoomList,
                        classHourMap, teacherRuleList, courseRuleList, leaveList, subGroupList);
            }
        }

        log.info("#CampusScheduling.start#--校区：" + campusId
                + "按行政班排课结束，"
                + "剩余排课单元数量：" + (leaveList != null ? leaveList.size() : 0)
                +"，可用教室课时分组数量：" + (timeslotRoomList!=null?timeslotRoomList.size():0));

        return leaveList;

    }

    public LinkedList<TeachingClassUnit> courseStart(Integer taskId,
                                                    String campusId,
                                                    List<ArrangeTeachingClassDto> teachingClassList,
                                                    LinkedList<TimeslotRoom> timeslotRoomList,
                                                    ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap,
                                                    List<ArrangeTeacherRuleDto> teacherRuleList,
                                                    List<ArrangeCourseRuleDto> courseRuleList,
                                                    LinkedList<TeachingClassUnit> leaveList,
                                                    List<SubClassGroup> subGroupList) {
        log.info("#CampusScheduling.start#--校区：" + campusId
                + "按課程排课开始"
                + "排课教学班数量：" + (teachingClassList != null ? teachingClassList.size() : 0));

        leaveList = mergeClassStart(taskId, campusId,
                teachingClassList, timeslotRoomList, classHourMap,
                teacherRuleList, courseRuleList, leaveList, subGroupList);

        subClassStart(taskId, campusId,
                teachingClassList, timeslotRoomList, classHourMap,
                teacherRuleList, courseRuleList, new LinkedList<>(), subGroupList);


        if (teachingClassList != null && !teachingClassList.isEmpty()) {
            log.info("#CampusScheduling.start#--校区：" + campusId
                    + "按课程排课开始"
                    + "课程排课开始"
                    + "排课教学班数量：" + (teachingClassList != null ? teachingClassList.size() : 0)
                    + "剩余合班排课单元数量：" + (leaveList != null ? leaveList.size() : 0)
            );
            Map<Long, List<ArrangeTeachingClassDto>> classMap = teachingClassList.stream().collect(Collectors.groupingBy(ArrangeTeachingClassDto::getCourseId));
            for (Map.Entry<Long, List<ArrangeTeachingClassDto>> entry : classMap.entrySet()) {
                leaveList = start(taskId, campusId, entry.getValue(), timeslotRoomList,
                        classHourMap, teacherRuleList, courseRuleList, leaveList, subGroupList);
            }
        }

        log.info("#CampusScheduling.start#--校区：" + campusId
                + "按课程排课结束，"
                + "剩余排课单元数量：" + (leaveList != null ? leaveList.size() : 0)
                +"，可用教室课时分组数量：" + (timeslotRoomList!=null?timeslotRoomList.size():0));

        return leaveList;

    }

    private LinkedList<TeachingClassUnit> subClassStart(Integer taskId, String campusId, List<ArrangeTeachingClassDto> teachingClassList, LinkedList<TimeslotRoom> timeslotRoomList, ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap, List<ArrangeTeacherRuleDto> teacherRuleList, List<ArrangeCourseRuleDto> courseRuleList, LinkedList<TeachingClassUnit> leaveList, List<SubClassGroup> subGroupList) {
        log.info("#CampusScheduling.start#--校区：" + campusId
                + "按课程排课开始"
                + "拆班排课开始"
                + "排课教学班数量：" + (teachingClassList != null ? teachingClassList.size() : 0));
        //筛选教学班列表中，需要拆班的教学班信息；
        List<ArrangeTeachingClassDto> splitTeachingClassList = findSplitTeachingClass(teachingClassList);

        if (splitTeachingClassList != null && !splitTeachingClassList.isEmpty()) {
            log.info("#CampusScheduling.start#--校区：" + campusId
                    + "按课程排课开始"
                    + "拆班排课开始"
                    + "拆班排课教学班数量：" + (splitTeachingClassList != null ? splitTeachingClassList.size() : 0));
            leaveList = start(taskId, campusId,
                    splitTeachingClassList, timeslotRoomList, classHourMap,
                    teacherRuleList, courseRuleList, leaveList, subGroupList);
        }
        log.info("#CampusScheduling.start#--校区：" + campusId
                + "按课程排课开始"
                + "拆班排课结束"
                + "剩余排课教学班数量：" + (teachingClassList != null ? teachingClassList.size() : 0));
        return leaveList;
    }

    private List<ArrangeTeachingClassDto> findSplitTeachingClass(List<ArrangeTeachingClassDto> teachingClassList) {
        //用于保存教师优先排排课的教学班信息列表；
        List<ArrangeTeachingClassDto> splitTeachingClassList = new ArrayList<>();
        if (teachingClassList != null && !teachingClassList.isEmpty()) {
            //定义列表遍历的迭代器
            Iterator iterator = teachingClassList.iterator();
            while (iterator.hasNext()) {
                ArrangeTeachingClassDto teachingClass = (ArrangeTeachingClassDto)iterator.next();
                //判断如果是拆班的教学班,单双号标识不为空，并且指定了教室，说明是单双号拆班的教学班
                //单双号标识为空，说明是常规拆班的教学班
                if (StringUtils.isNotBlank(teachingClass.getUniqueShiftSign())
                        && teachingClass.getIsSingle() !=null
                        &&teachingClass.getRoomId()!= null) {
                    //不为空就将这个教学班加入到尽量排的教学班列表中
                    splitTeachingClassList.add(teachingClass);
                    //从原来的教学班中，将尽量排的教学班剔除，剩下的进行自动排课
                    iterator.remove();
                }
            }
        }

        return splitTeachingClassList;
    }


    private LinkedList<TeachingClassUnit> mergeClassStart(Integer taskId,
                                                          String campusId,
                                                          List<ArrangeTeachingClassDto> teachingClassList,
                                                          LinkedList<TimeslotRoom> timeslotRoomList,
                                                          ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap,
                                                          List<ArrangeTeacherRuleDto> teacherRuleList,
                                                          List<ArrangeCourseRuleDto> courseRuleList,
                                                          LinkedList<TeachingClassUnit> leaveList,
                                                          List<SubClassGroup> subGroupList) {

        if (teachingClassList != null && !teachingClassList.isEmpty()) {
            List<ArrangeTeachingClassDto> mergeTeachingClassList = teachingClassList.stream()
                    .filter(teachingClass -> StrUtil.isNotEmpty(teachingClass.getToClass())
                                    && teachingClass.getToClass().contains(",")
//                                && teachingClass.getToClass().split(",").length > 1
                    )
                    .collect(Collectors.toList());
            teachingClassList.removeAll(mergeTeachingClassList);

            log.info("#CampusScheduling.start#--校区：" + campusId
                    + "按行政班排课开始"
                    + "合班排课开始"
                    + "排课教学班数量：" + (teachingClassList != null ? teachingClassList.size() : 0));

            leaveList = start(taskId, campusId,
                    mergeTeachingClassList, timeslotRoomList, classHourMap,
                    teacherRuleList, courseRuleList, leaveList, subGroupList);
        }
        log.info("#CampusScheduling.start#--校区：" + campusId
                + "按行政班排课开始"
                + "合班排课结束"
                + "剩余排课教学班数量：" + (teachingClassList != null ? teachingClassList.size() : 0)
                + "剩余合班排课单元数量：" + (leaveList != null ? leaveList.size() : 0)
        );
        return leaveList;
    }


    /**
     * 开始校区无冲突排课
     * @param taskId 排课选课计划id
     * @param campusId 校区id
     * @param teachingClassList 排课教学班
     * @param timeslotRoomList 教室课时分组
     * @param classHourMap 已排的正常课程，转换过来的排课单元map对象，key为timeslotCode
     * @param teacherRuleList 教师规则列表
     * @param courseRuleList 课程排课规则信息列表
     * @param leaveList 剩余的排课教学班排课单元列表
     * @return
     */
    public LinkedList<TeachingClassUnit> start(Integer taskId,
                       String campusId,
                       List<ArrangeTeachingClassDto> teachingClassList,
                       LinkedList<TimeslotRoom> timeslotRoomList,
                       ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap,
                       List<ArrangeTeacherRuleDto> teacherRuleList,
                       List<ArrangeCourseRuleDto> courseRuleList,
                       LinkedList<TeachingClassUnit> leaveList,
                       List<SubClassGroup> subGroupList) {

        //合班排课，东华需求
        LinkedList<TeachingClassUnit> mergerClassLeaveList = mergeTeachingClassScheduling(taskId, campusId, ruleInit, teachingClassList,
                timeslotRoomList, classHourMap, teacherRuleList, courseRuleList, new LinkedList<>(), true);

        mergerClassLeaveList = mergeTeachingClassScheduling(taskId, campusId, ruleInit, teachingClassList,
                timeslotRoomList, classHourMap, teacherRuleList, courseRuleList, mergerClassLeaveList, false);

        //合并周次
        leaveList = mergeTeachingClassWeekScheduling(taskId, campusId, ruleInit, teachingClassList,
                timeslotRoomList, classHourMap, teacherRuleList, courseRuleList, leaveList);

//        leaveList = splitScheduling(taskId, campusId, ruleInit, teachingClassList,
//                timeslotRoomList, classHourMap, leaveList, subGroupList);
        //拆班排课，鮀滨职校需求
        LinkedList<TeachingClassUnit> noSchedule = splitScheduling(taskId, campusId, ruleInit, teachingClassList,
                timeslotRoomList, teacherRuleList, courseRuleList, classHourMap, null, subGroupList, true);
        //拆班排课，鮀滨职校需求
        splitScheduling(taskId, campusId, ruleInit, null,
                timeslotRoomList,teacherRuleList, courseRuleList,  classHourMap, noSchedule, subGroupList, false);

        //优先排指定教室排课
        leaveList = fixScheduling(taskId, campusId, ruleInit, teachingClassList,
                timeslotRoomList, classHourMap, teacherRuleList, courseRuleList, leaveList);
        //指定教室排课
        leaveList = fixRoomScheduling(taskId, campusId, ruleInit, teachingClassList,
                timeslotRoomList, classHourMap, leaveList);

        //优先排未指定教室排课
        leaveList = fixNoRoomScheduling(taskId, campusId, ruleInit, teachingClassList,
                timeslotRoomList, classHourMap, leaveList);

        log.info("#CampusScheduling.start#--校区：" + campusId
                + "开始进行第一轮无冲突排课，并且启用基础规则过滤，"
                + "教学班数量：" +(teachingClassList!=null?teachingClassList.size():0)
                + "剩余排课教学班单元数量：" + (leaveList!=null?leaveList.size():0)
                + "可用教室课时分组数量：" + (timeslotRoomList!=null?timeslotRoomList.size():0));

        //开启第一轮无冲突排课，启用基础规则做过滤，同时会进行跨校区规则、冲突、禁排规则的检测
        leaveList =  noClashScheduing.start(taskId, teachingClassList,
                leaveList, timeslotRoomList, classHourMap);

        log.info("#CampusScheduling.start#--校区：" + campusId
                + "第一轮无冲突排课结束，"
                +"剩余教学班排课单元数量：" + (leaveList!=null?leaveList.size():0)
                +"，可用教室课时分组数量：" + (timeslotRoomList!=null?timeslotRoomList.size():0));

        leaveList.addAll(mergerClassLeaveList);
        //第二轮排课
//        if (leaveList != null && !leaveList.isEmpty()) {
//            log.info("#CampusScheduling.start#----校区：" + campusId
//                    +"开始进行第二轮无冲突排课，不启用基础规则过滤");
//
//            //第二轮选课，重新设置规则检测服务
//            noClashScheduing.setRuleService(ruleInit.getNoClashRule());
//            //开启第二轮无冲突排课，不检测基础规则
//            leaveList = noClashScheduing.start(taskId, null, leaveList, timeslotRoomList, classHourMap);
//
//            log.info("#CampusScheduling.start#----校区：" + campusId
//                    +"第二轮无冲突排课结束，"
//                    +"剩余教学班排课单元数量：" + (leaveList!=null?leaveList.size():0)
//                    +"，可用教室课时分组数量：" + (timeslotRoomList!=null?timeslotRoomList.size():0));
//        }

        return leaveList;
    }

    private LinkedList<TeachingClassUnit> mergeTeachingClassWeekScheduling(Integer taskId, String campusId,
                                                                           RuleInit ruleInit,
                                                                           List<ArrangeTeachingClassDto> teachingClassList,
                                                                           LinkedList<TimeslotRoom> timeslotRoomList,
                                                                           ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap,
                                                                           List<ArrangeTeacherRuleDto> teacherRuleList, List<ArrangeCourseRuleDto> courseRuleList, LinkedList<TeachingClassUnit> leaveList) {
        log.info("#CampusScheduling.mergeTeachingClassWeekScheduling#--校区：" + campusId
                +"开始进行合并授课方式排课");

        //需要拆班的教学班的排课处理，去指定教学班的教室课时分组信息
        LinkedList<TeachingClassUnit> mergeTeachingClassWeekList = new MergeTeachingClassWeekScheduling(ruleInit)
                .start(taskId, teachingClassList,
                        timeslotRoomList, classHourMap, teacherRuleList, courseRuleList);

        log.info("#CampusScheduling.mergeTeachingClassWeekScheduling#--校区：" + campusId
                +"合并授课方式排课完毕，剩余未排教学班排课单元数量："+ (mergeTeachingClassWeekList!=null?mergeTeachingClassWeekList.size():0));

        //如果剩余的排课教学班列表不为空
        if (mergeTeachingClassWeekList != null && !mergeTeachingClassWeekList.isEmpty()) {
            //加入进行处理
//            leaveList.addAll(mergeTeachingClassWeekList);
            SchedulingProcessData.addLeaveListMap(taskId, mergeTeachingClassWeekList);
        }

        return  leaveList;
    }

    /**
     * 合班排
     * @param taskId 排课选课计划id
     * @param campusId 校区id
     * @param ruleInit 初始化排课规则
     * @param teachingClassList 所有待排课的教学班信息列表
     * @param timeslotRoomList 所有待分配的教室课时分组信息列表
     * @param classHourMap 所有已分配的课表信息
     * @param teacherRuleList
     * @param courseRuleList
     * @param leaveList 剩余未分配的排课单元信息
     * @param withRule 是否进行优先排
     * @return
     */
    private LinkedList<TeachingClassUnit> mergeTeachingClassScheduling(Integer taskId,
                                                                       String campusId,
                                                                       RuleInit ruleInit,
                                                                       List<ArrangeTeachingClassDto> teachingClassList,
                                                                       LinkedList<TimeslotRoom> timeslotRoomList,
                                                                       ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap,
                                                                       List<ArrangeTeacherRuleDto> teacherRuleList, List<ArrangeCourseRuleDto> courseRuleList,
                                                                       LinkedList<TeachingClassUnit> leaveList,
                                                                       boolean withRule) {
        log.info("#CampusScheduling.mergeTeachingClassScheduling#--校区：" + campusId
                +"开始进行合班排排课");
        //尽量排规则的处理，其实就是根据尽量排规则，去指定教学班的教室课时分组信息
        LinkedList<TeachingClassUnit> mergeTeachingClassList = new MergeTeachingClassScheduling(ruleInit,withRule)
                .start(taskId, teachingClassList, timeslotRoomList, classHourMap, teacherRuleList, courseRuleList, leaveList, withRule);

        log.info("#CampusScheduling.mergeTeachingClassScheduling#--校区：" + campusId
                +"合班排课完毕，剩余未排教学班排课单元数量："+ (mergeTeachingClassList!=null?mergeTeachingClassList.size():0));
        leaveList.clear();
        //如果剩余的排课教学班列表不为空
        if (mergeTeachingClassList != null && !mergeTeachingClassList.isEmpty()) {
            //加入进行处理
            leaveList.addAll(mergeTeachingClassList);
//            SchedulingProcessData.addLeaveListMap(taskId, mergeTeachingClassList);
        }

        return  leaveList;
    }

    /**
     * 拆班排课，鮀滨职校需求
     * @param taskId 排课选课计划id
     * @param campusId 校区id
     * @param ruleInit 初始化排课规则
     * @param teachingClassList 所有待排课的教学班信息列表
     * @param timeslotRoomList 所有待分配的教室课时分组信息列表
     * @param classHourMap 所有已分配的课表信息
     * @param leaveList 剩余未分配的排课单元信息
     * @return
     */
    private LinkedList<TeachingClassUnit> splitScheduling(Integer taskId,
                                          String campusId,
                                          RuleInit ruleInit,
                                          List<ArrangeTeachingClassDto> teachingClassList,
                                          LinkedList<TimeslotRoom> timeslotRoomList,
                                          List<ArrangeTeacherRuleDto> teacherRuleList,
                                          List<ArrangeCourseRuleDto> courseRuleList,
                                          ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap,
                                          LinkedList<TeachingClassUnit> leaveList,
                                          List<SubClassGroup> subGroupList,
                                          boolean wittRule) {
        log.info("#CampusScheduling.splitScheduling#--校区：" + campusId
                +"开始进行拆班排课");

        //需要拆班的教学班的排课处理，去指定教学班的教室课时分组信息
        LinkedList<TeachingClassUnit> splicClassList = new SplitTeachingClassScheduling(ruleInit,wittRule)
                .start(taskId, teachingClassList, leaveList,
                        timeslotRoomList, teacherRuleList, courseRuleList,classHourMap, subGroupList, wittRule);

        log.info("#CampusScheduling.SplitScheduling#--校区：" + campusId
                +"拆班排课完毕，剩余未排教学班排课单元数量："+ (splicClassList!=null?splicClassList.size():0));

        LinkedList<TeachingClassUnit> noSchedule = new LinkedList<>();
        //如果剩余的排课教学班列表不为空
        if (splicClassList != null && !splicClassList.isEmpty()) {
            //加入进行处理
//            leaveList.addAll(splicClassList);
            if (wittRule){
                noSchedule.addAll(splicClassList);
            }else {
                SchedulingProcessData.addLeaveListMap(taskId, splicClassList);
            }
        }

        return  noSchedule;
    }

    /**
     * 固排指定教室排课
     * @param taskId 排课选课计划id
     * @param campusId 校区id
     * @param ruleInit 初始化排课规则
     * @param teachingClassList 所有待排课的教学班信息列表
     * @param timeslotRoomList 所有待分配的教室课时分组信息列表
     * @param classHourMap 所有已分配的课表信息
     * @param teacherRuleList 教师规则列表
     * @param courseRuleList 课程排课规则信息列表
     * @param leaveList 剩余未分配的排课单元信息
     * @return
     */
    private LinkedList<TeachingClassUnit> fixScheduling(Integer taskId,
                                        String campusId,
                                        RuleInit ruleInit,
                                        List<ArrangeTeachingClassDto> teachingClassList,
                                        LinkedList<TimeslotRoom> timeslotRoomList,
                                        ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap,
                                        List<ArrangeTeacherRuleDto> teacherRuleList,
                                        List<ArrangeCourseRuleDto> courseRuleList,
                                        LinkedList<TeachingClassUnit> leaveList) {
        log.info("#CampusScheduling.fixScheduling#--校区：" + campusId
                +"开始进行优先排排课");
        //尽量排规则的处理，其实就是根据尽量排规则，去指定教学班的教室课时分组信息
        LinkedList<TeachingClassUnit> fixClassList = new FixScheduling(ruleInit).start(taskId,
                teachingClassList, teacherRuleList, courseRuleList, timeslotRoomList, classHourMap);

        log.info("#CampusScheduling.fixScheduling#--校区：" + campusId
                +"优先排排课完毕，剩余未排教学班排课单元数量："+ (fixClassList!=null?fixClassList.size():0));

        //如果剩余的排课教学班列表不为空
        if (fixClassList != null && !fixClassList.isEmpty()) {
            //加入进行处理
            leaveList.addAll(fixClassList);
//            SchedulingProcessData.addLeaveListMap(taskId, fixClassList);
        }

        return  leaveList;
    }

    /**
     * 固排未指定教室排课
     *
     * @param taskId            排课选课计划id
     * @param campusId          校区id
     * @param ruleInit          初始化排课规则
     * @param teachingClassList 所有待排课的教学班信息列表
     * @param timeslotRoomList  所有待分配的教室课时分组信息列表
     * @param classHourMap      所有已分配的课表信息
     * @param leaveList         剩余未分配的排课单元信息
     * @return
     */
    private LinkedList<TeachingClassUnit> fixNoRoomScheduling(Integer taskId,
                                                              String campusId,
                                                              RuleInit ruleInit,
                                                              List<ArrangeTeachingClassDto> teachingClassList,
                                                              LinkedList<TimeslotRoom> timeslotRoomList,
                                                              ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap,
                                                              LinkedList<TeachingClassUnit> leaveList) {
        log.info("#CampusScheduling.fixNoRoomScheduling#--校区：" + campusId
                + "开始进行固排未指定教室排课");
        //尽量排规则的处理，其实就是根据尽量排规则，去指定教学班的教室课时分组信息
        LinkedList<TeachingClassUnit> fixClassList = new FixScheduling(ruleInit).fixNoRoomScheduling(taskId,
                teachingClassList, timeslotRoomList, classHourMap);

        log.info("#CampusScheduling.fixScheduling#--校区：" + campusId
                + "固排未指定教室排课完毕，剩余未排教学班排课单元数量：" + (fixClassList != null ? fixClassList.size() : 0));

        //如果剩余的排课教学班列表不为空
        if (fixClassList != null && !fixClassList.isEmpty()) {
            //加入进行处理
            leaveList.addAll(fixClassList);
        }

        return leaveList;
    }

    /**
     * 拆班排课，鮀滨职校需求
     * @param taskId 排课选课计划id
     * @param campusId 校区id
     * @param ruleInit 初始化排课规则
     * @param teachingClassList 所有待排课的教学班信息列表
     * @param timeslotRoomList 所有待分配的教室课时分组信息列表
     * @param classHourMap 所有已分配的课表信息
     * @param leaveList 剩余未分配的排课单元信息
     * @return
     */
    private LinkedList<TeachingClassUnit> fixRoomScheduling(Integer taskId,
                                    String campusId,
                                    RuleInit ruleInit,
                                    List<ArrangeTeachingClassDto> teachingClassList,
                                    LinkedList<TimeslotRoom> timeslotRoomList,
                                    ConcurrentHashMap<String, CopyOnWriteArrayList<ClassHour>> classHourMap,
                                    LinkedList<TeachingClassUnit> leaveList) {
        log.info("#CampusScheduling.fixRoomScheduling#--校区：" + campusId
                +"开始进行指定教室排课");
        //尽量排规则的处理，其实就是根据尽量排规则，去指定教学班的教室课时分组信息
        LinkedList<TeachingClassUnit> fixRoomList = new FixRoomScheduling(ruleInit).start(taskId, teachingClassList,
                timeslotRoomList, leaveList, classHourMap);

        log.info("#CampusScheduling.fixRoomScheduling#--校区：" + campusId
                +"指定教室排课完毕，剩余未排教学班排课单元数量："+ (fixRoomList!=null?fixRoomList.size():0));

        //如果剩余的排课教学班列表不为空
        if (fixRoomList != null && !fixRoomList.isEmpty()) {
            //加入进行处理
            leaveList.addAll(fixRoomList);
//            SchedulingProcessData.addLeaveListMap(taskId, fixRoomList);
        }

        return  leaveList;
    }


}
